package com.srit.recipes.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.srit.recipes.common.parent.DaoInject;
import com.srit.recipes.common.response.JpaPage;
import com.srit.recipes.entity.ProcurementDetailInfo;
import com.srit.recipes.entity.RecipesInfo;
import com.srit.recipes.entity.WeekRecipes;
import com.srit.recipes.entity.WeekRecipesDetail;
import com.srit.recipes.service.RecipesService;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.transaction.Transactional;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackOn = Exception.class)
public class RecipesServiceImpl extends DaoInject implements RecipesService {


    @Override
    public List<WeekRecipesDetail> recommend(int type) throws IOException {
        JSONArray recipes = JSONObject.parseArray(String.join("", Files.readAllLines(Paths.get("native/recipes-" + type + ".json"))));
        Map<String, Integer> breakfast = new HashMap<>();
        breakfast.put("JBL1", 1);
        breakfast.put("JBL2", 1);
        breakfast.put("JBL3", 1);
        breakfast.put("JBL4", 1);
        breakfast.put("JBL6", 2);
        breakfast.put("JBL7", 1);
        breakfast.put("JBL8", 1);
        breakfast.put("JBL9", 1);
        breakfast.put("JBL10", 1);
        breakfast.put("JBL11", 1);
        Map<String, Integer> lunch = new HashMap<>();
        lunch.put("JBL12", 2);
        lunch.put("JBL13", 1);
        lunch.put("JBL10", 3);
        lunch.put("JBL14", 1);
        lunch.put("JBL6", 1);
        lunch.put("JBL15", 2);
        lunch.put("JBL5", 1);
        Map<String, Integer> dinner = new HashMap<>();
        dinner.put("JBL12", 2);
        dinner.put("JBL13", 1);
        dinner.put("JBL10", 3);
        dinner.put("JBL14", 1);
        dinner.put("JBL6", 1);
        dinner.put("JBL15", 2);
        dinner.put("JBL5", 1);


        int size = recipes.size();
        Random random = new Random();

        JSONArray weekRecipes = recipes.getJSONArray(random.nextInt(size));

        List<WeekRecipesDetail> recipesData = new ArrayList<>();

        for (int i = 0; i < weekRecipes.size(); i++) {

            // 每天的
            JSONObject day = weekRecipes.getJSONObject(i);

            for (int j = 1; j < 16; j++) {
                String typeId = "JBL" + j;

                JSONArray detail = day.getJSONArray(typeId);

                // 早餐
                int typeSize = breakfast.getOrDefault(typeId, 0);
                int index = 0;
                addRecipes(recipesData, detail, typeSize, index, typeId, WeekRecipesDetail.breakfast, i);
                index += typeSize;


                // 中餐
                typeSize = lunch.getOrDefault(typeId, 0);
                addRecipes(recipesData, detail, typeSize, index, typeId, WeekRecipesDetail.lunch, i);
                index += typeSize;


                // 晚餐
                typeSize = dinner.getOrDefault(typeId, 0);
                addRecipes(recipesData, detail, typeSize, index, typeId, WeekRecipesDetail.dinner, i);

            }

        }

        return recipesData;
    }


    private void addRecipes(List<WeekRecipesDetail> recipesData, JSONArray detail, int size, int index, String typeId, String time, int week) {
        for (int t = index; t < index + size; t++) {
            String foodId = detail.getString(t);
            RecipesInfo recipesInfo = recipesInfoMap.get(foodId);

            WeekRecipesDetail weekRecipesDetail = new WeekRecipesDetail();
            weekRecipesDetail.setWeek(week);
            weekRecipesDetail.setRecipesId(foodId);
            weekRecipesDetail.setRate(1);
            weekRecipesDetail.setTime(time);
            weekRecipesDetail.setType(typeId);
            if (recipesInfo != null) {
                weekRecipesDetail.setRecipesName(recipesInfo.getCpName());
            }
            recipesData.add(weekRecipesDetail);
        }
    }

    @Override
    public WeekRecipes currentRecipes(int id) {
        WeekRecipes weekRecipes = weekRecipesDao.getById(id);

        List<WeekRecipesDetail> allByWeekRecipesId = weekRecipesDetailDao.findAllByWeekRecipesId(weekRecipes.getId());
        weekRecipes.setDetails(allByWeekRecipesId);

        return weekRecipes;
    }

    @Override
    public WeekRecipes saveRecommend(List<WeekRecipesDetail> weekRecipes, int type) {

        WeekRecipes save = new WeekRecipes();
        save.setPerNum(100);
        save.setType(type);
        save = weekRecipesDao.save(save);

        for (WeekRecipesDetail weekRecipe : weekRecipes) {
            weekRecipe.setWeekRecipesId(save.getId());
        }

        weekRecipes = weekRecipesDetailDao.saveAll(weekRecipes);
        save.setDetails(weekRecipes);
        return save;
    }

    @Override
    public JpaPage recipesHistory(JpaPage jpaPage, WeekRecipes weekRecipes) {

        if (weekRecipes.getState() == null) {
            return JpaPage.build(weekRecipesDao.findAll(JpaPage.getPageable(jpaPage, Sort.by("createTime").descending())));
        }

        ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("recipesName", ExampleMatcher.GenericPropertyMatchers.contains());

        Example<WeekRecipes> example = Example.of(weekRecipes, exampleMatcher);
        return JpaPage.build(weekRecipesDao.findAll(example, JpaPage.getPageable(jpaPage, Sort.by("createTime").descending())));
    }

    @Override
    public WeekRecipesDetail addOrUpdateDetail(WeekRecipesDetail recipesDetail) {
        return weekRecipesDetailDao.save(recipesDetail);
    }

    @Override
    public WeekRecipes addOrUpdateWeekRecipes(WeekRecipes weekRecipes) {
        return weekRecipesDao.save(weekRecipes);
    }

    @Override
    public boolean deleteWeekRecipes(int id) {
        weekRecipesDao.deleteById(id);
        weekRecipesDetailDao.deleteAllByWeekRecipesId(id);
        return true;
    }

    @Override
    public boolean deleteWeekRecipesDetail(int id) {
        weekRecipesDetailDao.deleteById(id);
        return true;
    }

    @Override
    public List<RecipesInfo> recipesList(String key, JpaPage page) {
        return recipesInfoMap.values()
                .stream()
                .filter(x -> !StringUtils.hasLength(key) || x.getCpName().contains(key))
                .skip((long) page.getPageSize() * (page.getPageNum() - 1))
                .limit(page.getPageSize())
                .collect(Collectors.toList());
    }

    @Override
    public Object submitRecipesExamine(int id) {
        WeekRecipes weekRecipes = weekRecipesDao.getById(id);

        weekRecipes.setState(WeekRecipes.IN_EXAMINE);
        return weekRecipes;
    }

    @Override
    public Object recipesExamine(WeekRecipes weekRecipes) {
        WeekRecipes save = weekRecipesDao.getById(weekRecipes.getId());
        save.setState(weekRecipes.getState());
        save.setExamineMsg(weekRecipes.getExamineMsg());
        weekRecipesDao.save(save);
        return save;
    }

    @Override
    public Object recipesExamineList(JpaPage jpaPage) {
        return JpaPage.build(weekRecipesDao.findAllByState(WeekRecipes.IN_EXAMINE, JpaPage.getPageable(jpaPage, Sort.by("createTime").descending())));
    }

    @Override
    public Object recipesExaminePass(JpaPage jpaPage) {
        return JpaPage.build(weekRecipesDao.findAllByState(WeekRecipes.EXAMINE_PASS, JpaPage.getPageable(jpaPage, Sort.by("createTime").descending())));
    }
}
